package com.shinbada.modules.sys.service;

import com.shinbada.common.ResultCode;
import com.shinbada.common.utils.CacheUtils;
import com.shinbada.common.utils.IdGen;
import com.shinbada.common.utils.StringUtils;
import com.shinbada.core.persistence.Page;
import com.shinbada.core.service.CrudService;
import com.shinbada.exception.ServiceException;
import com.shinbada.modules.sys.entity.DictType;
import com.shinbada.modules.sys.entity.DictValue;
import com.shinbada.modules.sys.mapper.DictTypeMapper;
import com.shinbada.modules.sys.mapper.DictValueMapper;
import com.shinbada.modules.sys.utils.DictUtils;
import com.shinbada.modules.sys.utils.UserUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 数据字典Service
 *
 * @author initcap
 * @version 2017-01-16
 */
@Service
@Transactional(readOnly = true)
public class DictTypeService extends CrudService<DictTypeMapper, DictType> {

    @Autowired
    private DictValueMapper dictValueMapper;

    @Override
    public DictType get(String id) {
        DictType dictType = super.get(id);
        dictType.setDictValueList(dictValueMapper.findList(new DictValue(dictType)));
        return dictType;
    }

    public DictValue getDictValue(String id) {
        return dictValueMapper.get(id);
    }

    @Override
    public List<DictType> findList(DictType dictType) {
        return super.findList(dictType);
    }

    @Override
    public Page<DictType> findPage(Page<DictType> page, DictType dictType) {
        return super.findPage(page, dictType);
    }

    public List<DictType> getDict() {
        List<DictType> types = mapper.getDict();
        types.forEach(dictType -> dictType.setDictValueList(dictValueMapper.findList(new DictValue(dictType))));
        return types;
    }

    @Override
    @Transactional(readOnly = false)
    public void save(DictType dictType) {
        saveBeforeCheck(dictType);
        super.save(dictType);
        CacheUtils.remove(DictUtils.CACHE_DICT_MAP);
    }

    @Transactional(readOnly = false)
    public void saveDictValue(DictValue dictValue) {
        saveDictValueBeforeCheck(dictValue);
        if (StringUtils.isBlank(dictValue.getId())) {
            dictValue.preInsert();
            dictValueMapper.insert(dictValue);
        } else {
            dictValue.preUpdate();
            dictValueMapper.update(dictValue);
        }
        CacheUtils.remove(DictUtils.CACHE_DICT_MAP);
    }

    private void saveDictValueBeforeCheck(DictValue dictValue) {
        if (checkDictValueExist(dictValue.getId(), dictValue.getCompanyId(), dictValue.getDictType().getId(), dictValue.getValue())) {
            throw new ServiceException(ResultCode.DICT_VALUE_EXIST);
        }
    }

    private boolean checkDictValueExist(String id, String companyId, String typeId, String value) {
        return dictValueMapper.countDictValue(id, companyId, typeId, value) > 0;
    }

    @Transactional(readOnly = false)
    public void deleteDictValue(DictValue dictValue) {
        dictValueMapper.delete(dictValue);
        CacheUtils.remove(DictUtils.CACHE_DICT_MAP);
    }

    @Transactional(readOnly = false)
    public void batchDeleteDictValue(String[] ids) {
        dictValueMapper.batchDelete(ids);
        CacheUtils.remove(DictUtils.CACHE_DICT_MAP);
    }

    @Override
    @Transactional(readOnly = false)
    public void delete(DictType dictType) {
        super.delete(dictType);
        dictValueMapper.delete(new DictValue(dictType));
        CacheUtils.remove(DictUtils.CACHE_DICT_MAP);
    }

    public boolean containsSystemDict(String[] idArray) {
        return mapper.countSystemDictInIds(idArray) > 0;
    }

    private void saveBeforeCheck(DictType dictType) {
        if (checkDictTypeExist(dictType.getId(), dictType.getType())) {
            throw new ServiceException(ResultCode.DICT_TYPE_EXIST);
        }
    }

    private boolean checkDictTypeExist(String id, String type) {
        return mapper.countDictType(id, type) > 0;
    }

    public List<DictValue> getDictList(String type) {
        return dictValueMapper.listByType(type, UserUtils.getUser().getCompany().getId());
    }

    @Transactional(readOnly = false)
    public void appendDictValue(String type, DictValue dictValue) {
        DictType dictType = mapper.getByType(type);
        if (dictType == null) {
            throw new ServiceException(ResultCode.DICT_TYPE_NOT_EXIST);
        }
        dictValue.setDictType(dictType);
        dictValue.setId("");
        saveDictValue(dictValue);
    }

    @Transactional(readOnly = false)
    public void copyDictValueByCompanyId(String sourceCompanyId, String targetCompanyId) {
        List<DictValue> dictValues = dictValueMapper.listByCompanyid(sourceCompanyId);
        if (CollectionUtils.isEmpty(dictValues)) {
            throw new ServiceException(ResultCode.COMPANY_ID_NOT_EXIST_OR_EMPTY_DICT);
        }
        dictValues.forEach(dictValue -> {
            dictValue.setId(IdGen.uuid());
            dictValue.setIsNewRecord(true);
            dictValue.setCompanyId(targetCompanyId);
            dictValue.preInsert();
            dictValueMapper.insert(dictValue);
        });
        if (dictValueMapper.countByCompanyid(targetCompanyId) == 0) {
            throw new ServiceException(ResultCode.DICT_COPY_ERR);
        }
    }
}
